package svc.elib.util;


/**
 * <p>Title: StringUtil</p>
 *
 * <p>Description: Defines generally useful String,  
 * StringBuilder or StringBuffer manipulation methods</p>
 *
 */

public final class StringUtil {
	
	/**
	 * A helper method to compare all objects by CONTENT that implement CharSequence interface, 
	 * for example: StringBuilder, String, StringBuffer 
	 * @param left
	 * @param right
	 * @return false when different or at least one is null
	 */
	public final static boolean equalsContent(final CharSequence left,
			final CharSequence right) {
		if (left == null || right == null)
			return false;

		int n = left.length();
		if (n == right.length()) {			
			while( n-- != 0 ) 
			  if ( left.charAt( n ) != right.charAt( n ) ) return false;
			return true;
		}
		return false;
	}

	/**
	 * A helper method to compare all objects by Lowercased CONTENT that implement CharSequence interface, 
	 * for example: StringBuilder, String, StringBuffer 
	 * @param left
	 * @param right
	 * @return false when different or at least one is null
	 */
	public static boolean equalsContentIgnoreCase(final CharSequence left,
			final CharSequence right) {
		if (left == null || right == null)
			return false;

		int n = left.length();
		if (n == right.length()) {			
			while( n-- != 0 ) 
			  if ( Character.toLowerCase(left.charAt( n )) != Character.toLowerCase(right.charAt( n )) ) return false;
			return true;
		}
		return false;
	}
	
	
	/**
	 * A helper method to compare lexicographicaly objects by CONTENT that implement CharSequence interface, 
	 * for example: StringBuilder, String, StringBuffer 
	 * @param left
	 * @param right
	 * @return 0-equal -1-left is smaller 1-left is bigger
	 */
	public static int compareContent(final CharSequence left,
			final CharSequence right) {
	  
		final int l1 = left.length();
		final int l2 = right.length();
		final int n = l1 < l2 ? l1 : l2;
		

		for( int i = 0; i < n; i++ ){
		  final char l = left.charAt(i);
		  final char r = right.charAt(i);
		  if ( left.charAt(i) != right.charAt(i) )
		    return l - r;
		}

		return l1 - l2;
	}
	
	


	
    public static final boolean stripDoubles(final StringBuilder s) {
        boolean doneSomething = false;
        
        int len = s.length();
        if(len <= 3) return false;           
        
        for(int i = 2; i < len; i++){
            final char left =  s.charAt(i);
            if((left== s.charAt(i-1)) && !Character.isDigit(left)){ // oh, and don't mess up numbers!
                s.deleteCharAt(i);
                len--;
                i--;
                doneSomething = true;
            }
        }
        return doneSomething;
    }


     public static final boolean stripDoubles(final MutableString s) {
            boolean doneSomething = false;
            
            int len = s.length();
            if(len <= 3) return false;           
            final char[] a = s.array();
            
            for(int i = 2; i < len; i++){
                final char left =  a[i];
                // not (left < '0' && left > '9'), because for example 'n' > '9' but not 'n' < '0' and we
                // get here false for character n for example
                if((left == a[i-1]) && !(left>='0' && left <='9')){ // oh, and don't mess up numbers!
                    s.deleteCharAt(i);
                    len--;
                    i--;
                    doneSomething = true;
                }
            }
            
            return doneSomething;
          }
     
     /**
      * strip doubles in mutable string that is not tokenized; strip doubles is done 
      * only in case that token has length > 3
      * 
      * @param s
      * @return true if input mutable string is changed, false otherwise
      */
    public static final boolean stripDoublesOnMultipleTokens(final MutableString s) {
    	 boolean doneSomething = false;
    	 
    	 int tokenLen = 0;
    	 
    	 int len = s.length();
    	 if (len <= 3)
    		 return false;
    	 
    	 for (int i = 2; i < len; i++) {
    		 final char curr = s.charAt(i);
    		 final char prev = s.charAt(i - 1);
    		 
    		 if (curr == ' ' || curr == '\t') {
    			 // reset token length
    			 tokenLen = 0;
    		 }
    		 else {
    			 if (prev == curr && (prev<'0' && prev >'9')) {
    				 boolean hasMinimalLength = true;
    				 
    				 if (tokenLen < 3) {
    					 // check lookahed characters 
    					 for (int j = 0; j <= 3 - tokenLen; j++) {
    						 if (i + j < len) {
    							 char lookahead = s.charAt(i + j);
    							 if (!Character.isLetter(lookahead)) {
    								 hasMinimalLength = false;
    								 break;
    							 }
    						 }
    						 else {
    							 // end of sentence
    							 hasMinimalLength = false;
    							 break;
    						 }
    							
    					 }
    				 }
    				 
    				 if (hasMinimalLength) {
    					 s.deleteCharAt(i);
    					 len--;
    					 i--;
    					 doneSomething = true;
    				 }
    			 }
    			 
    			 tokenLen++;
    		 }
    	 }
    	 
    	 return doneSomething;
     }
     
     
/**
 * Old good Trim whitespace, does leading and trailnig
 * @param s
 */	 
		public static void trimWs(final StringBuilder s){			
			if(s==null) return;
			int len = s.length();
	        
			// left trim
			while(len > 0 && s.charAt(0) == ' '){
	              s.deleteCharAt(0);
	              len--;
	        }
	        
	        // right trim
	        while(len > 0 && s.charAt(len-1)==' '){
	            --len;
	        	s.setLength(len);
	        }
		}
	 
	
		
	 public static final int indexOf(StringBuilder sb, char c, int i){
		 int len = sb.length();
		 
		 if(i >= len) {
		    return -1;
		 } else  if(i < 0) {
		    i = 0;
		 } 
		 
		 while(i < len){
			 if(c == sb.charAt(i)){
				 return i;
			 }
			 i++;
		 }
		 return -1;
	 }
	 
}
